package com.demo.statemachine.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.StateMachinePersist;
import org.springframework.statemachine.service.StateMachineService;
import org.springframework.stereotype.Controller;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class StateMachineController {
    private final StateMachineListener listener = new StateMachineListener();
    private StateMachine<States, Events> currentStateMachine;

    @Autowired
    private StateMachineService<States, Events> stateMachineService;

    @Autowired
    private StateMachinePersist<States, Events, String> stateMachinePersist;


    @RequestMapping("/test")
    @ResponseBody
    public String test(@RequestParam(value = "machine") String machine) throws Exception {
        StateMachine<States, Events> stateMachine = getStateMachine(machine);
        for (Events event : Events.values()) {
            stateMachine.sendEvent(event);
        }
        return "success";
    }

    private synchronized StateMachine<States, Events> getStateMachine(String machineId) throws Exception {
        listener.resetMessages();
        if (currentStateMachine == null) {
            currentStateMachine = stateMachineService.acquireStateMachine(machineId);
            currentStateMachine.addStateListener(listener);
            currentStateMachine.start();
        } else if (!ObjectUtils.nullSafeEquals(currentStateMachine.getId(), machineId)) {
            stateMachineService.releaseStateMachine(currentStateMachine.getId());
            currentStateMachine.stop();
            currentStateMachine = stateMachineService.acquireStateMachine(machineId);
            currentStateMachine.addStateListener(listener);
            currentStateMachine.start();
        }
        return currentStateMachine;
    }
}
